from fastapi.requests import Request
from pydantic import BaseModel, EmailStr

from utils.api_resopnse import api_response
from utils.cache.local_memory import LocalMemoryCache
from utils.drivers.database.models.message import Message
from utils.enums import MessageStatus
from utils.exception import AppException, StatusCode
from utils.helper import get_session_id, generate_uuid
from utils.i18n.i18n import i18n


class Params(BaseModel):
    name: str
    tel: str
    email: str
    content: str
    verify_code: str

async def receive_message(request: Request, params: Params):
    # 验证联系方式
    if not params.name:
        raise AppException(
            code=StatusCode.ContactInformationError,
            message=i18n(language=request.state.language, key="message_tip_name"),
            detail=params.name
        )

    if not params.tel and not params.email:
        raise AppException(
            code=StatusCode.ContactInformationError,
            message=i18n(language=request.state.language, key="message_tip_tel_or_email"),
            detail=params.tel
        )

    # 验证电话
    if params.tel and not all(char.isdigit() or char == '-' for char in params.tel):
        raise AppException(
            code=StatusCode.ContactInformationError,
            message=i18n(language=request.state.language, key="message_tip_tel_error"),
            detail=params.tel
        )

    # 验证邮箱
    if params.email:
        try:
            EmailStr._validate(params.email)
        except ValueError:
            raise AppException(
                code=StatusCode.ContactInformationError,
                message=i18n(language=request.state.language, key="message_tip_email_error"),
                detail=params.email
            )

    # 验证留言内容
    if not 2 < len(params.content) < 500:
        raise AppException(
            code=StatusCode.MessageContentError,
            message=i18n(language=request.state.language, key="message_tip_content"),
            detail=params.content
        )

    # 验证验证码
    session_id = get_session_id(request)
    cache = LocalMemoryCache()
    if cache.get(session_id + "_captcha") != params.verify_code.upper():
        raise AppException(
            code=StatusCode.VerifyCodeError,
            message=i18n(language=request.state.language, key="message_tip_verify_error"),
            detail=params.verify_code
        )

    # 限制1分钟内只能提交3次留言
    messages = cache.hgetall(session_id + "_message")
    if len(messages) >= 3:
        raise AppException(
            code=StatusCode.MessageLimitError,
            message=i18n(language=request.state.language, key="message_tip_limit")
        )

    ip = request.client.host

    # 保存留言
    message = Message(
        username=params.name,
        tel=params.tel,
        email=params.email,
        ip=ip,
        content=params.content,
        status=MessageStatus.Unread.value
    )
    await message.save()

    cache.hset(session_id + "_message", generate_uuid(), None, ex=60)

    return api_response(
        message=i18n(language=request.state.language, key="message_tip_success"),
    )
